﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace DawnOfConquest
{
    class TacMap
    {
        private int width = 10;
        private Tile[][] map;
        //private List<Tile> validMoves;
        private List<Tile> targets;

        //terrain
        private Texture2D woods;
        private Texture2D mountains;
        private Texture2D river;

        public TacMap(Tile[][] map, ContentManager content)
        {
            this.map = map;
            //validMoves = new List<Tile>();
            //TODO load all unit sprites and terrain sprites and effects sprites for drawing
        }

        public void addTile(Tile tile, int xCoor, int yCoor)
        {
            // places tile in the given coordinates
            map[xCoor][yCoor] = tile;
        }

        public List<Tile> getNeighbors(Tile tile, List<Tile> neighbors)
        {
            //returns the neighbors of the given tile and adds them to existing list
            //at most, will return 4 tiles
            int xCoord = tile.getXCoord();
            int yCoord = tile.getYCoord();

            //MAYBE TODO, getNeighbors and find moves back to working order

            //prevent array index out of bounds and check for existence of tile in list
            if (xCoord > 0 && !neighbors.Contains(map[xCoord - 1][yCoord]))
            {
                neighbors.Add(map[xCoord - 1][yCoord]);
            }
            if (xCoord < width && !neighbors.Contains(map[xCoord + 1][yCoord]))
            {
                neighbors.Add(map[xCoord + 1][yCoord]);
            }
            if (yCoord > 0 && !neighbors.Contains(map[xCoord][yCoord - 1]))
            {
                neighbors.Add(map[xCoord][yCoord - 1]);
            }
            if (yCoord < width && !neighbors.Contains(map[xCoord][yCoord + 1]))
            {
                neighbors.Add(map[xCoord][yCoord + 1]);
            }
            return neighbors;
        }

        public bool isNeighbor(Tile tile1, Tile tile2)
        {
            //returns true if the given tiles are neighbors
            //two tiles are neighbors if either their xCoords or yCoords are one apart (but not both)
            int xCoord1 = tile1.getXCoord();
            int yCoord1 = tile1.getYCoord();
            int xCoord2 = tile2.getXCoord();
            int yCoord2 = tile2.getYCoord();
            if (Math.Abs(xCoord1 - xCoord2) == 1 && (yCoord1 - yCoord2 == 0))
            {
                return true;
            }
            else if (Math.Abs(yCoord1 - yCoord2) == 1 && (xCoord1 - xCoord2 == 0))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public void draw(SpriteBatch spriteBatch, ContentManager content)
        {
            //Draws the map background then goes through every tile and calls tile.draw(X,Y) depending on the tile’s location in the array
            //TODO modify so that for each tile's terrain and unit are drawn in this class by
            //finding what is in the tile and draw it using the loaded sprites in this class
            Vector2 location;

            for (int i = 0; i < map.GetLength(0); i++)
                for (int j = 0; j < map.GetLength(1); j++)
                {
                    location = new Vector2(i * 30, j * 30);
                    map[i][j].draw(i * 30, j * 30, spriteBatch, content);
                    //TODO if tile.terrain = whatever draw whatever at position i j
                    //draw unit class at location using peice draw method which takes vector and spritebatch
                    //if validMoves contains tile then put green box on it

                }
        }

        //TODO similar to valid moves, find a list of all tiles within 

        public List<Tile> findValidMoves(Piece piece)
        {
            //List<Tile> validMoves = new List<Tile>();
            piece.validMoves = new List<Tile>();
            findMoves(piece.getLocation(), piece.getAP(), piece);
            return piece.validMoves;
        }

        private void findMoves(Tile location, int ap, Piece piece)
        {
            int remainingPoints = ap;
            List<Tile> neighbors = getNeighbors(location, new List<Tile>());

            for (int i = 0; i < neighbors.Count; i++)
            {
                Tile tile = neighbors[i];
                int cost;
                if (tile.getTerrain().Equals("Plain"))
                {
                    cost = 1;
                }
                else if (tile.getTerrain().Equals("Woods"))
                {
                    cost = 2;
                }
                else if (tile.getTerrain().Equals("Mountain"))
                {
                    cost = 4;
                }
                else
                {
                    cost = 999;
                }
                if (remainingPoints >= cost && !piece.validMoves.Contains(neighbors[i]))
                {
                    if (neighbors[i].isEmpty())
                    {
                        piece.validMoves.Add(neighbors[i]);
                        findMoves(neighbors[i], remainingPoints - cost, piece);
                        return;
                    }
                    else
                    {
                        if (neighbors[i].getResident().getFaction().Equals(piece.getFaction()))
                        {
                            findMoves(neighbors[i], remainingPoints - cost, piece);
                            return;
                        }
                        else
                        {
                            return;
                        }
                    }
                }
                else
                {
                    return;
                }
            }
        }


        public String movePiece(Tile origin, Tile destination, Piece piece)
        {
            if (piece.validMoves.Contains(destination))
            {
                origin.removePiece();
                origin.enterPiece(piece);
                // promptAbility();
                piece.move();
                piece.validMoves = null;
                return piece.getName() + " has moved";

            }
            else
                return "invalid location";
        }

        public void randomMap()
        {
            //constructs a randomly generated map
            //start by setting every tile to be plains
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < width; j++)
                {
                    map[i][j] = new Tile("Plain", i, j);
                }
            }
            //determine how many types of terrain will be on the map
            Random r = new Random();
            int typesOfTerrain = r.Next(2) + 1;

            bool water = false;
            bool mountain = false;
            bool woods = false;
            //now figure out which of these should be true

            if (typesOfTerrain == 1 || typesOfTerrain == 2)
            {
                int n = r.Next(2);
                //0 = water
                //1 = mountain
                //2 = woods
                if (typesOfTerrain == 1)
                {
                    if (n == 0)
                        water = true;
                    else if (n == 1)
                        mountain = true;
                    else if (n == 2)
                        woods = true;
                }
                if (typesOfTerrain == 2)
                {
                    if (n == 0)
                    {
                        mountain = true;
                        woods = true;
                    }
                    else if (n == 1)
                    {
                        water = true;
                        woods = true;
                    }
                    else if (n == 2)
                    {
                        water = true;
                        mountain = true;
                    }
                }
            }

            if (water)
            {
                //up to 25 tiles can be water
                int numberOfWater = r.Next(25) + 1;
                int n = 0;
                while (n < numberOfWater)
                {
                    //pick a random tile, and if the tile is plains, change into water
                    int x = r.Next(width);
                    int y = r.Next(width);
                    if (map[x][y].getTerrain().Equals("Plain"))
                    {
                        map[x][y] = new Tile("Water", x, y);
                        n++;
                    }
                }
            }

            if (mountain)
            {
                //up to 20 tiles can be mountains
                //mountains shouldn't block off an entire section of the map
                int numberOfMountains = _r.Next(25) + 1;
                int n = 0;
                while (n < numberOfMountains)
                {
                    //pick a random tile, and if the tile is plains, change into mountains
                    int x = r.Next(width);
                    int y = r.Next(width);
                    if (map[x][y].getTerrain().Equals("Plain"))
                    {
                        map[x][y] = new Tile("Mountain", x, y);
                        n++;
                    }
                }
            }

            if (woods)
            {
                //up to 40 tiles can be woods
                //woods can go anywhere
                int numberOfWoods = r.Next(40) + 1;
                int n = 0;
                while (n < numberOfWoods)
                {
                    //pick a random tile, and if the tile is plains, change into woods
                    int x = r.Next(width);
                    int y = r.Next(width);
                    if (map[x][y].getTerrain().Equals("Plain"))
                    {
                        map[x][y] = new Tile("Woods", x, y);
                        n++;
                    }
                }
            }
        }

        public Tile getTile(int x, int y)
        { return map[x][y]; }

        public List<Tile> getValidMoves()
        { return validMoves; }

    }
}